#include "com_voe_VoEBase.h"
#include "jni_api.h"
#include "OutputParam.h"
#include "voe_base.h"
#include "audio_device.h"
#include "VoiceEngineObserverImpl.h"

static VoiceEngineObserverImpl _VoiceEngineObserver;

/*
 * Class:     com_voe_VoEBase
 * Method:    GetInterface
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_com_voe_VoEBase_GetInterface
	(JNIEnv* env, jclass cls, jlong p_voiceEngine)
{
	return (jlong)webrtc::VoEBase::GetInterface((webrtc::VoiceEngine*)p_voiceEngine);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    Release
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_Release
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->Release();
}

/*
 * Class:     com_voe_VoEBase
 * Method:    RegisterVoiceEngineObserver
 * Signature: (JLcom/voe/callback/VoiceEngineObserver;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_RegisterVoiceEngineObserver
  (JNIEnv* env, jclass cls, jlong p, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	if(_VoiceEngineObserver.set(env, obj))
	{
		return pVoEBase->RegisterVoiceEngineObserver(_VoiceEngineObserver);
	}
	return JCB_Err_Set;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    DeRegisterVoiceEngineObserver
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_DeRegisterVoiceEngineObserver
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	jint result = pVoEBase->DeRegisterVoiceEngineObserver();
	if(result == 0)
		_VoiceEngineObserver.unset(env);
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    Init
 * Signature: (JLcom/voe/AudioDeviceModule;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_Init
  (JNIEnv* env, jclass cls, jlong p, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	webrtc::AudioDeviceModule* external_adm = 0;
	if(obj)
	{
		external_adm = (webrtc::AudioDeviceModule*)
			JniHelper::getLongField(env, obj,
				JniHelper::getFieldID(env,
					JniHelper::getClassByObject(env, obj), "_p", "J"));
	}
	return pVoEBase->Init(external_adm);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    Terminate
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_Terminate
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->Terminate();
}

/*
 * Class:     com_voe_VoEBase
 * Method:    MaxNumOfChannels
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_MaxNumOfChannels
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->MaxNumOfChannels();
}

/*
 * Class:     com_voe_VoEBase
 * Method:    CreateChannel
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_CreateChannel
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->CreateChannel();
}

/*
 * Class:     com_voe_VoEBase
 * Method:    DeleteChannel
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_DeleteChannel
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->DeleteChannel(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    SetLocalReceiver
 * Signature: (JIIILjava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_SetLocalReceiver
	(JNIEnv* env, jclass cls, jlong p, jint channel, jint port, jint RTCPport, jstring ipAddr, jstring multiCastAddr)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	std::string str_ipAddr;
	std::string str_multiCastAddr;
	const char* sz_ipAddr = 0;
	const char* sz_multiCastAddr = 0;

	if(ipAddr)
	{
		str_ipAddr = JniHelper::j2c_string(env, ipAddr);
		sz_ipAddr = str_ipAddr.c_str();
	}

	if(multiCastAddr)
	{
		str_multiCastAddr = JniHelper::j2c_string(env, multiCastAddr);
		sz_multiCastAddr = str_multiCastAddr.c_str();
	}

	return pVoEBase->SetLocalReceiver(channel, port, RTCPport, sz_ipAddr,
		sz_multiCastAddr);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetLocalReceiver
 * Signature: (JILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_GetLocalReceiver
  (JNIEnv* env, jclass cls, jlong p, jint channel, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	char ipAddr[64] = {0};
	int port, RTCPport;
	jint result = pVoEBase->GetLocalReceiver(channel, port, RTCPport, ipAddr);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add(port).add(RTCPport).add(std::string(ipAddr)).getOutput());
	}
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    SetSendDestination
 * Signature: (JIILjava/lang/String;II)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_SetSendDestination
  (JNIEnv* env, jclass cls, jlong p, jint channel , jint port, jstring ipAddr, jint sourcePort, jint RTCPport)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->SetSendDestination(channel, port, JniHelper::j2c_string(env, ipAddr).c_str(),
		sourcePort, RTCPport);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetSendDestination
 * Signature: (JILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_GetSendDestination
	(JNIEnv* env, jclass cls, jlong p, jint channel, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	char ipAddr[64] = {0};
	int port, sourcePort, RTCPport;
	jint result = pVoEBase->GetSendDestination(channel, port, ipAddr, sourcePort, RTCPport);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add(port).add(std::string(ipAddr)).add(sourcePort).add(RTCPport).getOutput());
	}
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StartReceive
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StartReceive
  (JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StartReceive(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StopReceive
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StopReceive
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StopReceive(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StartPlayout
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StartPlayout
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StartPlayout(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StopPlayout
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StopPlayout
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StopPlayout(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StartSend
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StartSend
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StartSend(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    StopSend
 * Signature: (JI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_StopSend
	(JNIEnv* env, jclass cls, jlong p, jint channel)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->StopSend(channel);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetVersion
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_voe_VoEBase_GetVersion
  (JNIEnv* env, jclass cls, jlong p)
{
	jstring result = 0;
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	char version[1024] = {0};
	int ret = pVoEBase->GetVersion(version);
	if(ret == 0)
	{
		result = JniHelper::c2j_string(env, version);
	}
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    LastError
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_LastError
  (JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->LastError();
}

/*
 * Class:     com_voe_VoEBase
 * Method:    SetOnHoldStatus
 * Signature: (JIZI)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_SetOnHoldStatus
	(JNIEnv* env, jclass cls, jlong p, jint channel, jboolean enable, jint mode)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->SetOnHoldStatus(channel, enable!=0, (webrtc::OnHoldModes)mode);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetOnHoldStatus
 * Signature: (JILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_GetOnHoldStatus
  (JNIEnv* env, jclass cls, jlong p, jint channel, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	bool enabled;
	webrtc::OnHoldModes mode;
	jint result = pVoEBase->GetOnHoldStatus(channel, enabled, mode);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add(enabled).add((int)mode).getOutput());
	}
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    SetNetEQPlayoutMode
 * Signature: (JII)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_SetNetEQPlayoutMode
  (JNIEnv* env, jclass cls, jlong p, jint channel, jint mode)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->SetNetEQPlayoutMode(channel, (webrtc::NetEqModes)mode);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetNetEQPlayoutMode
 * Signature: (JILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_GetNetEQPlayoutMode
	(JNIEnv* env, jclass cls, jlong p, jint channel, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	webrtc::NetEqModes mode;
	jint result = pVoEBase->GetNetEQPlayoutMode(channel, mode);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add((int)mode).getOutput());
	}
	return result;
}

/*
 * Class:     com_voe_VoEBase
 * Method:    SetNetEQBGNMode
 * Signature: (JII)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_SetNetEQBGNMode
  (JNIEnv* env, jclass cls, jlong p, jint channel, jint mode)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	return pVoEBase->SetNetEQBGNMode(channel, (webrtc::NetEqBgnModes)mode);
}

/*
 * Class:     com_voe_VoEBase
 * Method:    GetNetEQBGNMode
 * Signature: (JILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEBase_GetNetEQBGNMode
	(JNIEnv * env, jclass cls, jlong p, jint channel, jobject obj)
{
	webrtc::VoEBase* pVoEBase = (webrtc::VoEBase*)p;
	webrtc::NetEqBgnModes mode;
	jint result = pVoEBase->GetNetEQBGNMode(channel, mode);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add((int)mode).getOutput());
	}
	return result;
}
